package com.bsh.serviceImpl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.alibaba.fastjson.JSONObject;
import com.bsh.mybatis.model.AccountNotice;
import com.bsh.mybatis.model.Payment;
import com.bsh.repository.DaoAccountNotice;
import com.bsh.repository.DaoPayment;
import com.bsh.service.AccountService;
import com.bsh.service.PaymentService;
import com.bsh.utils.Constants;
import com.bsh.utils.MD5;
import com.bsh.utils.PrimaryGenerater;

/**
 * 支付方式列表
 * 
 * @author jane
 *
 */
@Service
@Transactional
public class PaymentServiceImpl implements PaymentService {
	private static Logger log = LoggerFactory
			.getLogger(PaymentServiceImpl.class);
	@Autowired
	private DaoPayment daoPay;

	@Autowired
	private DaoAccountNotice daoAccNotice;
	@Autowired
	private AccountService accountSer;

	@Override
	public List<Map<String, Object>> getPaymentList(String type) {

		List<Map<String, Object>> paymentList = daoPay.getPaymentList(type);
		return paymentList;
	}

	/**
	 * 微信支付保存请求信息
	 * 
	 * @param map
	 */
	@Override
	public void wxPayment(JSONObject jsonObj) throws Exception {
		// 从MAP中取出
		AccountNotice an = new AccountNotice();
		an.setTitle(jsonObj.getString("title"));
		an.setAccountId(jsonObj.getInteger("account_id"));
		an.setUserid(jsonObj.getInteger("userid"));
		an.setMoney(new BigDecimal(jsonObj.getInteger("money")));
		an.setOperator(jsonObj.getInteger("userid"));
		an.setTradeType(jsonObj.getInteger("tradeType"));
		an.setPaymentId(32);
		an.setSn(PrimaryGenerater.getInstance().next());
		an.setIsPaid(new Byte("0"));
		an.setMoneyType((short) 1);
		an.setCreateTime(new Date());
		int i = daoAccNotice.insert(an);
		if (i > 0) {
			System.out.println("保存成功");
		} else {
			System.out.println("保存失败");
		}
	}

	/**
	 * 微信支付第三方回调
	 * 
	 * @param map
	 */
	@Override
	@Transactional
	public Integer backWxPayment(JSONObject jsonObj) throws Exception {
		Integer res = -1;
		// 1校验sign是否正确
		checkSign(jsonObj);

		JSONObject messageDetail = jsonObj.getJSONObject("message_detail");
		String sn = messageDetail.getString("out_trade_no"); // 商家内部交易号
		String outerSn = messageDetail.getString("transaction_id"); // 微信交易号

		// 查询出记录
		AccountNotice an = new AccountNotice();
		an.setSn(sn);
		an = daoAccNotice.selectBySn(an);
		if (an == null || an.equals("")) {
			// log.error( .. 记录日志 说明数据库里没有这条记录!!
			log.error("webHook_error:流水号数据库里没有[" + sn + "]");
			return 2;
		}
		if (an.getIsPaid() == 1) {
			// 已经支付成功并回调操作过业务了
			// log.info( 记录
			log.error("webHook_info:数据库已经是isPaid[" + sn + "]");
			return 3;
		}
		// 业务
		if (jsonObj.getString("transactionType").equals("PAY")) {
			String channelType = jsonObj.getString("channelType");
			switch (channelType) {
			case "WX":
				// 交易状态
				String resultCode = messageDetail.getString("result_code"); // 业务结果

				if (resultCode.equals("SUCCESS")) {
					// 支付成功
					// -----
					// 返回的金额 单位是分!!!
					BigDecimal resultTotal = jsonObj
							.getBigDecimal("transaction_fee");
					if (resultTotal.compareTo(new BigDecimal("0")) <= 0) {
						return -6;
					}
					if (resultTotal.divide(new BigDecimal("100"), 2,
							BigDecimal.ROUND_HALF_UP).compareTo(an.getMoney()) == 0) {

						// 业务三类: 转账给别人, 充值, 会员升级
						// 16-在线转账, 1用户充值,4会员升级
						Integer tradeType = an.getTradeType();
						switch (tradeType) {
						case 16:
							// 用户转账处理
							res = accountSer.financeTransferOnlineWebHook(sn,
									outerSn, resultCode);
							break;

						case 1:
							// 用户充值
							res = accountSer.financeRechargeWebHook(sn,
									outerSn, resultCode);
							break;
						case 4:
							// 会员升级
							res = accountSer.financeUpgradeMemberWebHook(sn,
									outerSn, resultCode);
							break;
						}

						if (res < 0) {
							// callback 主动回滚
							log.error("webHook_ERROR:主动回滚[" + sn + "]"
									+ tradeType + " res:" + res);
							TransactionAspectSupport.currentTransactionStatus()
									.setRollbackOnly();
							res = -12;
						}

					} else {
						// 金额不匹配
						log.error("webHook_ERROR:金额不匹配-7[" + sn + "]"
								+ resultTotal);
						return -7;
					}

				} else {
					// 支付失败
				}

				break;

			}
			return res;
		}

		return res;

	}

	/**
	 * 回调校验sign
	 * 
	 * @param jsonObj
	 * @throws Exception
	 */
	private void checkSign(JSONObject jsonObj) throws Exception {
		String sign = jsonObj.getString("sign");
		if (StringUtils.isBlank(sign)) {
			throw new Exception("参数中缺少sign");
		}
		String timestamp = jsonObj.getString("timestamp");
		if (StringUtils.isBlank(timestamp)) {
			throw new Exception("参数中缺少timestamp");
		}
		String md5Sign = MD5.GetMD5Code(Constants.getAppId() + Constants.getAppSecret()
				+ timestamp);
		if (!sign.equals(md5Sign)) {
			throw new Exception("非法操作，签名认证失败");
		}
	}

	@Override
	public Payment getPaymentByClassName(String className) {
		Payment result = daoPay.getPaymentByClassName(className);
		return result;
	}

	@Override
	public void ysbPayment(JSONObject jsonObj) throws Exception {
		// 从MAP中取出
		AccountNotice an = new AccountNotice();
		an.setTitle(jsonObj.getString("title"));
		an.setAccountId(jsonObj.getInteger("account_id"));
		an.setUserid(jsonObj.getInteger("userid"));
		an.setMoney(new BigDecimal(jsonObj.getInteger("money")));
		an.setOperator(jsonObj.getInteger("userid"));
		an.setTradeType(jsonObj.getInteger("tradeType"));
		an.setPaymentId(35); // 银生宝支付
		an.setSn(PrimaryGenerater.getInstance().next());
		an.setIsPaid(new Byte("0"));
		an.setMoneyType((short) 1);
		an.setCreateTime(new Date());
		int i = daoAccNotice.insert(an);
		if (i > 0) {
			System.out.println("保存成功");
		} else {
			System.out.println("保存失败");
		}
	}

	/**
	 * 银生宝回调逻辑判断
	 */
	@Override
	@Transactional
	public Integer backYsbPayment(JSONObject jsonObj) throws Exception {
		Integer res = -1;
		// 查询出记录
		AccountNotice an = new AccountNotice();
		an.setSn(jsonObj.getString("orderId"));
		an = daoAccNotice.selectBySn(an);
		if (an == null || an.equals("")) {
			// log.error( .. 记录日志 说明数据库里没有这条记录!!
			log.error("webHook_error:流水号数据库里没有[" + jsonObj.getString("orderId")
					+ "]");
			return 2;
		}
		if (an.getIsPaid() == 1) {
			// 已经支付成功并回调操作过业务了
			// log.info( 记录
			log.error("webHook_info:数据库已经是isPaid["
					+ jsonObj.getString("orderId") + "]");
			return 3;
		}

		// 成功处理
		else if (jsonObj.getString("result_code").equals("0000")) {
			log.info("成功处理，交易类型："+an.getTradeType());
			BigDecimal resultTotal = jsonObj.getBigDecimal("amount");
			if (resultTotal.compareTo(new BigDecimal("0")) <= 0) {
				return -6;
			}
			if (resultTotal.compareTo(an.getMoney()) == 0) {
				// 16-在线转账, 1用户充值,4会员升级
				Integer tradeType = an.getTradeType();
				switch (tradeType) {
				case 16:
					// 用户转账处理
					log.info("成功处理=16");
					res = accountSer.financeTransferOnlineWebHook(jsonObj.getString("orderId"),jsonObj.getString("orderId"), null);
					break;

				case 1:
					// 用户充值
					log.info("成功处理=1");
					res = accountSer.financeRechargeWebHook(jsonObj.getString("orderId"),jsonObj.getString("orderId"), null);
					break;
				case 4:
					// 会员升级
					log.info("成功处理=4");
					res = accountSer.financeUpgradeMemberWebHook(jsonObj.getString("orderId"),jsonObj.getString("orderId"), null);
					break;
				}
			} else {
				// 金额不匹配
				log.error("webHook_ERROR:金额不匹配-7["
						+ jsonObj.getString("orderId") + "]" + resultTotal);
				return -7;
			}
		}
		// 失败处理
		if (res < 0) {
			// callback 主动回滚
			log.error("webHook_ERROR:主动回滚[" + jsonObj.getString("orderId")
					+ "]" + an.getTradeType() + " res:" + res);
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
			res = -12;
		}
		log.info("处理完成");
		return res;

	}

}
